package com.cn.fw4j.util.groovy;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyClassLoader.InnerLoader;
import groovy.lang.GroovyObject;

import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

import org.codehaus.groovy.control.CompilationFailedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cn.fw4j.util.PropertiesHelper;

/**
 * Groovy 加载工具
 * @author user
 *
 */
public final class GroovyLoaderHelper {
	private static Logger logger = LoggerFactory.getLogger(GroovyLoaderHelper.class);
	private final static GroovyLoaderHelper instance = new GroovyLoaderHelper();
	/**
	 * 类加载器
	 */
	private final static ClassLoader parentLoader = Thread.currentThread().getContextClassLoader();
	/**
	 * Groovy 文件池
	 * key : 文件名
	 * value : 文件路径
	 */
	private final static Map<String,File> groovyPool = new LinkedHashMap<String,File>();
	private final static Map<String,Class<?>> gcPool = new LinkedHashMap<String,Class<?>>();
	private static boolean FW4J_GROOVY_CACHE = false;
	
	static{
		String val = PropertiesHelper.get("fw4j.properties", "FW4J_GROOVY_CACHE");
		if(val != null){
			FW4J_GROOVY_CACHE = Boolean.parseBoolean(val);
		}
	}
	
	private GroovyLoaderHelper(){}
	
	public final static GroovyLoaderHelper getInstance(){
		return instance;
	}
	/**
	 * 添加Groovy路径
	 * @param name 文件名
	 * @param path 路径
	 */
	public synchronized void putGroovyPath(String name,String path) {
		if(!groovyPool.containsKey(name)){
			logger.info(path);
			groovyPool.put(name, new File(path));
			return;
		}
		logger.error("class "+name+" 以存在");
	}
	/**
	 * 获取 Groovy 实例
	 * @param name
	 * @return GroovyObject
	 * @throws CompilationFailedException
	 * @throws IOException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public synchronized GroovyObject getGroovyInstance(String name) 
			throws CompilationFailedException, IOException, InstantiationException, IllegalAccessException{
		Class<?> cc = gcPool.get(name);
		if(cc == null || !FW4J_GROOVY_CACHE){
			cc = getGroovyClass(name);
			gcPool.put(name, cc);
		}
		return (GroovyObject)cc.newInstance();
	}

	/**
	 * 获取 Groovy Class
	 * @param name
	 * @return Class<?>
	 * @throws CompilationFailedException
	 * @throws IOException
	 */
	public synchronized Class<?> getGroovyClass(String name)
			throws CompilationFailedException, IOException{
		GroovyClassLoader gl = new GroovyClassLoader(parentLoader);
		InnerLoader il = new InnerLoader(gl);
		Class<?> ret = il.parseClass(groovyPool.get(name));
		il.close();
		return ret;
	}
}
